package com.linkgie.galaxyframework.crypto.context;

import java.io.InputStream;
import java.io.OutputStream;

import com.linkgie.galaxyframework.crypto.SymmetricCipherService;
import com.linkgie.galaxyframework.crypto.SymmetricCryptor;
import com.linkgie.galaxyframework.crypto.SymmetricKey;
import com.linkgie.galaxyframework.crypto.spi.SymmetricFuncSPI;
import com.linkgie.galaxyframework.crypto.spi.SymmetricKeybytes;

public class SymmetricCipherServiceImpl extends CryptoServiceBase<SymmetricFuncSPI> implements SymmetricCipherService {

	public SymmetricCipherServiceImpl(SymmetricFuncSPI innerService) {
		super(innerService);
	}

	@Override
	public SymmetricKey generateKey() {
		SymmetricKeybytes keyBytes = INNSER_SERVICE.generateKey();
		return ENCODING.encode(ALGORITHM, keyBytes);
	}

	@Override
	public SymmetricKey generateKey(byte[] seed) {
		SymmetricKeybytes keyBytes = INNSER_SERVICE.generateKey(seed);
		return ENCODING.encode(ALGORITHM, keyBytes);
	}

//	@Override
//	public byte[] encrypt(SymmetricKey key, byte[] plainBytes) {
//		SymmetricKeybytes keyBytes = ENCODING.decode(key);
//		return INNSER_SERVICE.encrypt(keyBytes, plainBytes);
//	}
//
//	@Override
//	public byte[] encrypt(SymmetricKey key, byte[] plainBytes, int offset, int length) {
//		SymmetricKeybytes keyBytes = ENCODING.decode(key);
//		return INNSER_SERVICE.encrypt(keyBytes, plainBytes, offset, length);
//	}
//
//	@Override
//	public int encrypt(SymmetricKey key, byte[] plainBytes, int offset, int length, OutputStream out) {
//		SymmetricKeybytes keyBytes = ENCODING.decode(key);
//		return INNSER_SERVICE.encrypt(keyBytes, plainBytes, offset, length, out);
//	}
//	
//	@Override
//	public byte[] encrypt(byte[] rawKey, byte[] plainBytes) {
//		return INNSER_SERVICE.encrypt(rawKey, plainBytes);
//	}
//	
//	@Override
//	public byte[] encrypt(byte[] rawKey, byte[] plainBytes, int offset, int length) {
//		return INNSER_SERVICE.encrypt(rawKey, plainBytes, offset, length);
//	}
//	
//	@Override
//	public int encrypt(byte[] rawKey, byte[] plainBytes, int offset, int length, OutputStream out) {
//		return INNSER_SERVICE.encrypt(rawKey, plainBytes, offset, length, out);
//	}
//	
//
//	@Override
//	public byte[] decrypt(SymmetricKey key, byte[] cipherBytes) {
//		SymmetricKeybytes keyBytes = ENCODING.decode(key);
//		return INNSER_SERVICE.decrypt(keyBytes, cipherBytes);
//	}
//
//	@Override
//	public byte[] decrypt(SymmetricKey key, byte[] cipherBytes, int offset, int length) {
//		SymmetricKeybytes keyBytes = ENCODING.decode(key);
//		return INNSER_SERVICE.decrypt(keyBytes, cipherBytes, offset, length);
//	}
//
//	@Override
//	public int decrypt(SymmetricKey key, byte[] cipherBytes, int offset, int length, OutputStream out) {
//		SymmetricKeybytes keyBytes = ENCODING.decode(key);
//		return INNSER_SERVICE.decrypt(keyBytes, cipherBytes, offset, length, out);
//	}
//	
//	@Override
//	public byte[] decrypt(byte[] rawKey, byte[] cipherBytes) {
//		return INNSER_SERVICE.decrypt(rawKey, cipherBytes);
//	}
//	
//	@Override
//	public byte[] decrypt(byte[] rawKey, byte[] cipherBytes, int offset, int length) {
//		return INNSER_SERVICE.decrypt(rawKey, cipherBytes, offset, length);
//	}
//	
//	@Override
//	public int decrypt(byte[] rawKey, byte[] cipherBytes, int offset, int length, OutputStream out) {
//		return INNSER_SERVICE.decrypt(rawKey, cipherBytes, offset, length, out);
//	}
	

	@Override
	public int encrypt(SymmetricKey key, InputStream in, OutputStream out) {
		SymmetricKeybytes keyBytes = ENCODING.decode(key);
		return INNSER_SERVICE.encrypt(keyBytes, in, out);
	}

	@Override
	public int encrypt(byte[] rawKey, InputStream in, OutputStream out) {
		return INNSER_SERVICE.encrypt(rawKey, in, out);
	}

	@Override
	public int decrypt(SymmetricKey key, InputStream in, OutputStream out) {
		SymmetricKeybytes keyBytes = ENCODING.decode(key);
		return INNSER_SERVICE.decrypt(keyBytes, in, out);
	}

	@Override
	public int decrypt(byte[] rawKey, InputStream in, OutputStream out) {
		return INNSER_SERVICE.decrypt(rawKey, in, out);
	}

	@Override
	public SymmetricCryptor createSymmetricCryptor(SymmetricKey key) {
		return new SymmetricCryptorAdapter(key);
	}

	@Override
	public SymmetricCryptor generateSymmetricCryptor() {
		SymmetricKeybytes keyBytes = INNSER_SERVICE.generateKey();
		return new SymmetricCryptorAdapter(keyBytes);
	}

	@Override
	public SymmetricCryptor generateSymmetricCryptor(byte[] seed) {
		SymmetricKeybytes keyBytes = INNSER_SERVICE.generateKey(seed);
		return new SymmetricCryptorAdapter(keyBytes);
	}

	
	private final class SymmetricCryptorAdapter implements SymmetricCryptor{
		
		private SymmetricKeybytes keyBytes;
		
		public SymmetricCryptorAdapter(SymmetricKey key) {
			this.keyBytes = ENCODING.decode(key);
		}
		
		public SymmetricCryptorAdapter(SymmetricKeybytes keyBytes) {
			this.keyBytes = keyBytes;
		}

		@Override
		public byte[] encrypt(byte[] plainBytes) {
			return INNSER_SERVICE.encrypt(keyBytes, plainBytes);
		}

		@Override
		public byte[] encrypt(byte[] plainBytes, int offset, int length) {
			return INNSER_SERVICE.encrypt(keyBytes, plainBytes, offset, length);
		}

		@Override
		public int encrypt(byte[] plainBytes, int offset, int length, OutputStream out) {
			return INNSER_SERVICE.encrypt(keyBytes, plainBytes, offset, length, out);
		}

		@Override
		public byte[] decrypt(byte[] cipherBytes) {
			return INNSER_SERVICE.decrypt(keyBytes, cipherBytes);
		}

		@Override
		public byte[] decrypt(byte[] cipherBytes, int offset, int length) {
			return INNSER_SERVICE.decrypt(keyBytes, cipherBytes, offset, length);
		}

		@Override
		public int decrypt(byte[] cipherBytes, int offset, int length, OutputStream out) {
			return INNSER_SERVICE.decrypt(keyBytes, cipherBytes, offset, length, out);
		}
		
	}


	
}
